﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace DMEditor
{
    public partial class frmMain : Form
    {
        public frmMain()
        {
            InitializeComponent();


        }

        private void frmMain_Load(object sender, EventArgs e)
        {
            try
            {
                // Load the 'kits' list with all 100 custom kits
                loadKits();

                for (int i = 0; i < DM10Kit.EQFrequencies.Length; ++i)
                {
                    ddlEqHfFreq.Items.Add(DM10Kit.EQFrequencies[i]);
                    ddlEqLfFreq.Items.Add(DM10Kit.EQFrequencies[i]);
                }

                listInstruments.SelectedIndex = 1; // Setup for CurrentLayer
                CurrentLayer = 0;                  // Layer A
                listInstruments.SelectedIndex = 0; // Select Kick1 as default instrument
            }
            catch(Exception ex)
            {
                Program.LogForm.AddLogItem("Error: " + ex);

                //MessageBox.Show("Error: " + ex);
                Close();

            }
            autoKitChangeToolStripMenuItem.Enabled = autoKitChangeToolStripMenuItem.Checked;



            // Set up kit effects
            ddlReverbType.SelectedIndex = 12; // RmSmlDrk
            ddlFxType.SelectedIndex = 1; // Mono Flanger
            ddlCompType.SelectedIndex = 14; // Rock3


        }

        public void loadKits()
        {
            
            for (int i = 0; i < 100; ++i)
            {
                stripKits.Items.Add((100 + i) + "  (" + Program.settings.kits[i].name + ")");
            }

            stripKits.SelectedIndex = 0; // Select kit 100 by default
        }

        private void settingsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (Program.SettingsForm.IsDisposed) Program.SettingsForm = new frmSettings();
            Program.SettingsForm.Show();
        }

        private void onlineModeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            onlineModeToolStripMenuItem.Checked = !onlineModeToolStripMenuItem.Checked;
            Program.module.Online = onlineModeToolStripMenuItem.Checked;

            if (onlineModeToolStripMenuItem.Checked == false) autoKitChangeToolStripMenuItem.Enabled = false;
            else autoKitChangeToolStripMenuItem.Enabled = true;
        }

        private void autoKitChangeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            autoKitChangeToolStripMenuItem.Checked = !autoKitChangeToolStripMenuItem.Checked;
            Program.module.autoKitChange = autoKitChangeToolStripMenuItem.Checked;
        }

        public void reloadSoundset()
        {
            ddlCategories.Items.Clear();

            for (int i = 0; i < Program.settings.soundset.categories.Count; ++i)
            {
                ddlCategories.Items.Add(Program.settings.soundset.categories[i]);
            }
        }

        public void updateInstrumentSettings(int instNumber, int currentLayer = 0)
        {
            if (instNumber < 0) return;

            CurrentLayer = currentLayer; // Change the visible layer to whichever one we have specified here

            ddlCategories.SelectedIndex = Program.settings.kits[currentKit].instruments[instNumber].instLayers[currentLayer].category;
            ddlInstruments.SelectedIndex = Program.settings.kits[currentKit].instruments[instNumber].instLayers[currentLayer].sound;

            udInstLevel.Value = Program.settings.kits[currentKit].instruments[instNumber].instLayers[currentLayer].level;
            trkInstPan.Value = Program.settings.kits[currentKit].instruments[instNumber].instLayers[currentLayer].pan;
            udInstDecay.Value = Program.settings.kits[currentKit].instruments[instNumber].instLayers[currentLayer].decay;
            udInstAttack.Value = Program.settings.kits[currentKit].instruments[instNumber].instLayers[currentLayer].attack;

            udInstReverb.Value = Program.settings.kits[currentKit].instruments[instNumber].instLayers[currentLayer].reverb;
            udInstEffects.Value = Program.settings.kits[currentKit].instruments[instNumber].instLayers[currentLayer].effects;
            chkInstEQOn.Checked = Program.settings.kits[currentKit].instruments[instNumber].instLayers[currentLayer].eq == 0 ? false : true;

            udInstSemitone.Value = Program.settings.kits[currentKit].instruments[instNumber].instLayers[currentLayer].semitone;
            udInstFinetune.Value = Program.settings.kits[currentKit].instruments[instNumber].instLayers[currentLayer].finetune;
            udInstFilter.Value = Program.settings.kits[currentKit].instruments[instNumber].instLayers[currentLayer].filter;

            udInstVelDecay.Value = Program.settings.kits[currentKit].instruments[instNumber].instLayers[currentLayer].velDecay;
            udInstVelFilter.Value = Program.settings.kits[currentKit].instruments[instNumber].instLayers[currentLayer].velFilter;
            udInstVelLevel.Value = Program.settings.kits[currentKit].instruments[instNumber].instLayers[currentLayer].velLevel;
            udInstVelPitch.Value = Program.settings.kits[currentKit].instruments[instNumber].instLayers[currentLayer].velPitch;

            ddlInstMuteGroup.SelectedIndex = Program.settings.kits[currentKit].instruments[instNumber].instLayers[currentLayer].muteGroup;

            ddlReverbType.SelectedIndex = Program.settings.kits[currentKit].reverbType;
            udReverbSize.Value = Program.settings.kits[currentKit].reverbSize;
            udReverbColor.Value = Program.settings.kits[currentKit].reverbColor; 
            udReverbLevel.Value = Program.settings.kits[currentKit].reverbLevel;
            
            ddlFxType.SelectedIndex = Program.settings.kits[currentKit].fxType;
            udFxLevel.Value = Program.settings.kits[currentKit].fxLevel;
            udFxDepth.Value = Program.settings.kits[currentKit].fxDepth;
            udFxDamp.Value = Program.settings.kits[currentKit].fxDamp;
            udFxRate.Value = Program.settings.kits[currentKit].fxRate;
            udFxFeedbackL.Value = Program.settings.kits[currentKit].fxFeedbackL;
            udFxFeedbackR.Value = Program.settings.kits[currentKit].fxFeedbackR;
            udFxDelayL.Value = Program.settings.kits[currentKit].fxDelayL;
            udFxDelayR.Value = Program.settings.kits[currentKit].fxDelayR;

            ddlCompType.SelectedIndex = Program.settings.kits[currentKit].compType;
            udCompLevel.Value = Program.settings.kits[currentKit].compLevel;
            udCompOutLevel.Value = Program.settings.kits[currentKit].compOutLevel;

            udEqLfGain.Value = Program.settings.kits[currentKit].eqLFGain;
            ddlEqLfFreq.SelectedIndex = Program.settings.kits[currentKit].eqLFFreq;
            udEqHfGain.Value = Program.settings.kits[currentKit].eqHFGain;
            ddlEqHfFreq.SelectedIndex = Program.settings.kits[currentKit].eqHFFreq;

            updatePanLabel();

            Output = Program.settings.kits[currentKit].instruments[instNumber].instLayers[currentLayer].output;
            Priority = Program.settings.kits[currentKit].instruments[instNumber].instLayers[currentLayer].priority;
            Playback = Program.settings.kits[currentKit].instruments[instNumber].instLayers[currentLayer].monoPlayback;
            FilterType = Program.settings.kits[currentKit].instruments[instNumber].instLayers[currentLayer].filtertype;

            // MIDI
            udMIDIChannel.Value = Program.settings.kits[currentKit].instruments[instNumber].midi.channel;
            udMIDINote.Value = Program.settings.kits[currentKit].instruments[instNumber].midi.note;
            ddlMIDIGateTime.SelectedIndex = Program.settings.kits[currentKit].instruments[instNumber].midi.gateTime;
            MIDINoteSent = Program.settings.kits[currentKit].instruments[instNumber].midi.sendNoteOff;

            MIDIChording = Program.settings.kits[currentKit].instruments[instNumber].midi.chordMode;
            udMIDIChordNote2.Value = Program.settings.kits[currentKit].instruments[instNumber].midi.note2 > 127 ? -1 : Program.settings.kits[currentKit].instruments[instNumber].midi.note2;
            udMIDIChordNote3.Value = Program.settings.kits[currentKit].instruments[instNumber].midi.note3 > 127 ? -1 : Program.settings.kits[currentKit].instruments[instNumber].midi.note3;
            udMIDIChordNote4.Value = Program.settings.kits[currentKit].instruments[instNumber].midi.note4 > 127 ? -1 : Program.settings.kits[currentKit].instruments[instNumber].midi.note4;

            

        }

        private int Output
        {
            get 
            {
                if (rdoOutputMain.Checked) return 0;
                else return 1; // aux
            }
            set 
            {
                if (value == 0) rdoOutputMain.Checked = true;
                else rdoOutputAux.Checked = true;
            }
        }

        private int Priority
        {
            get
            {
                if (rdoPriorityLow.Checked) return 0;
                else if (rdoPriorityMed.Checked) return 1;
                else return 2; // High priority
            }
            set
            {
                if (value == 0) rdoPriorityLow.Checked = true;
                else if (value == 1) rdoPriorityMed.Checked = true;
                else rdoPriorityHigh.Checked = true;
            }
        }

        private int Playback
        {
            get
            {
                if (rdoPlaybackMono.Checked) return 1;
                else return 0;
            }

            set
            {
                if (value == 1) rdoPlaybackMono.Checked = true;
                else rdoPlaybackPoly.Checked = true;
            }
        }

        private int FilterType
        {
            get
            {
                if (rdoFilterTypeHighpass.Checked) return 1;
                else return 0;
            }

            set
            {
                if (value == 1) rdoFilterTypeHighpass.Checked = true;
                else rdoFilterTypeLowpass.Checked = true;
            }

        }

        private short currentKit
        {
            get { return (short)stripKits.SelectedIndex; }
        }
        
        private int currentInst
        {
            get { return listInstruments.SelectedIndex; }
        }

        private int CurrentLayer
        {
            get
            {
                if (rdoLayerA.Checked) return 0;
                else return 1;
            }

            set
            {
                if (value == 0) rdoLayerA.Checked = true;
                else rdoLayerB.Checked = true;
            }

        }

        private int MIDINoteSent
        {
            get
            {
                if (rdoMIDINoteNotSent.Checked) return 0;
                else if (rdoMIDINoteSent.Checked) return 1;
                else return 2; // Alternate
            }

            set
            {
                if (value == 0) rdoMIDINoteNotSent.Checked = true;
                else if (value == 1) rdoMIDINoteSent.Checked = true;
                else rdoMIDINoteAlternate.Checked = true;
            }

        }

        private int MIDIChording
        {
            get
            {
                if (rdoMIDIChordOff.Checked) return 0;
                else if (rdoMIDIChord.Checked) return 1;
                else return 2; // Arpeggio
            }

            set
            {
                if (value == 0)
                {
                    rdoMIDIChordOff.Checked = true;

                    udMIDIChordNote2.Enabled = false;
                    udMIDIChordNote3.Enabled = false;
                    udMIDIChordNote4.Enabled = false;
                }
                else if (value == 1)
                {
                    rdoMIDIChord.Checked = true;

                    udMIDIChordNote2.Enabled = true;
                    udMIDIChordNote3.Enabled = true;
                    udMIDIChordNote4.Enabled = true;
                }
                else
                {
                    rdoMIDIChordArpeggio.Checked = true;
                 
                    udMIDIChordNote2.Enabled = true;
                    udMIDIChordNote3.Enabled = true;
                    udMIDIChordNote4.Enabled = true;
                }
            }

        }

        private void ddlCategories_SelectedIndexChanged(object sender, EventArgs e)
        {
            ddlInstruments.Items.Clear();
            for (int i = 0; i < Program.settings.soundset.instruments[ddlCategories.SelectedIndex].Count; ++i)
            {
                ddlInstruments.Items.Add(Program.settings.soundset.instruments[ddlCategories.SelectedIndex][i]);
            }

            if (ddlInstruments.Items.Count > 0)
            {
                ddlInstruments.Enabled = true;
            }
            else
            {
                ddlInstruments.Items.Add("None");
                ddlInstruments.Enabled = false;
            }

            //ddlInstruments.SelectedIndex = 0;
        }

        private void listInstruments_SelectedIndexChanged(object sender, EventArgs e)
        {
            Program.module.SendNRPN(NRPN.KitInstrument, (byte)currentInst);

            Program.module.suppressNRPNSend = true;
            updateInstrumentSettings(currentInst, CurrentLayer);
            Program.module.suppressNRPNSend = false;
        }

        private void stripKits_SelectedIndexChanged(object sender, EventArgs e)
        {
            Program.settings.currentKit = currentKit;

            if (Program.module.autoKitChange) Program.module.SendKitChange((byte)(currentKit + 100));

            updateInstrumentSettings(currentInst, CurrentLayer);
        }
        
        private void udInstLevel_ValueChanged(object sender, EventArgs e)
        {

            Program.settings.kits[currentKit].instruments[currentInst].instLayers[CurrentLayer].level = (short)udInstLevel.Value;

            Program.module.SendNRPN(NRPN.InstLayerLevel, (byte)udInstLevel.Value);
        }

        private void udInstDecay_ValueChanged(object sender, EventArgs e)
        {
            Program.settings.kits[currentKit].instruments[currentInst].instLayers[CurrentLayer].decay = (short)udInstDecay.Value;

            Program.module.SendNRPN(NRPN.InstLayerDecay, (byte)udInstDecay.Value);
        }

        private void udInstAttack_ValueChanged(object sender, EventArgs e)
        {
            Program.settings.kits[currentKit].instruments[currentInst].instLayers[CurrentLayer].attack = (short)udInstAttack.Value;

            Program.module.SendNRPN(NRPN.InstLayerAttack, (byte)udInstAttack.Value);
        }

        private void udInstReverb_ValueChanged(object sender, EventArgs e)
        {
            Program.settings.kits[currentKit].instruments[currentInst].instLayers[CurrentLayer].reverb = (short)udInstReverb.Value;

            Program.module.SendNRPN(NRPN.InstReverbSend, (byte)udInstReverb.Value);
        }

        private void udInstEffects_ValueChanged(object sender, EventArgs e)
        {
            Program.settings.kits[currentKit].instruments[currentInst].instLayers[CurrentLayer].effects = (short)udInstEffects.Value;

            Program.module.SendNRPN(NRPN.InstFxSend, (byte)udInstEffects.Value);
        }

        private void chkInstEQOn_CheckedChanged(object sender, EventArgs e)
        {
            Program.settings.kits[currentKit].instruments[currentInst].instLayers[CurrentLayer].eq = (chkInstEQOn.Checked ? 1 : 0);

            Program.module.SendNRPN(NRPN.InstCompSend, (byte)(chkInstEQOn.Checked ? 1 : 0));
        }

        private void udInstSemitone_ValueChanged(object sender, EventArgs e)
        {
            Program.settings.kits[currentKit].instruments[currentInst].instLayers[CurrentLayer].semitone = (short)udInstSemitone.Value;

            Program.module.SendNRPN(NRPN.InstLayerSemitones, (byte)(udInstSemitone.Value + 12));
        }

        private void udInstFinetune_ValueChanged(object sender, EventArgs e)
        {
            Program.settings.kits[currentKit].instruments[currentInst].instLayers[CurrentLayer].finetune = (short)udInstFinetune.Value;

            Program.module.SendNRPN(NRPN.InstLayerFine, (byte)(udInstFinetune.Value + 50));
        }

        private void udInstFilter_ValueChanged(object sender, EventArgs e)
        {
            Program.settings.kits[currentKit].instruments[currentInst].instLayers[CurrentLayer].filter = (short)udInstFilter.Value;

            Program.module.SendNRPN(NRPN.InstLayerFilter, (byte)udInstFilter.Value);
        }

        private void ddlInstMuteGroup_SelectedIndexChanged(object sender, EventArgs e)
        {
            Program.settings.kits[currentKit].instruments[currentInst].instLayers[CurrentLayer].muteGroup = (short)ddlInstMuteGroup.SelectedIndex;

            Program.module.SendNRPN(NRPN.InstMuteGroup, (byte)ddlInstMuteGroup.SelectedIndex);
        }

        private void udInstVelDecay_ValueChanged(object sender, EventArgs e)
        {
            Program.settings.kits[currentKit].instruments[currentInst].instLayers[CurrentLayer].velDecay = (short)udInstVelDecay.Value;

            byte val = (byte)(99 + udInstVelDecay.Value); // convert from -99 - +99 to 0 - 199

            //Program.LogForm.AddLogItem("val: " + val + ", val & 0x7F: " + (val & 0x7F) + ", val & 0x80: " + ((val & 0xF80) > 0 ? 1 : 0));

            Program.module.SendNRPN(NRPN.InstLayerVelDecay, (byte)(val & 0x7F), (byte)((val & 0x80) > 0 ? 1 : 0));
        }

        private void udInstVelFilter_ValueChanged(object sender, EventArgs e)
        {
            Program.settings.kits[currentKit].instruments[currentInst].instLayers[CurrentLayer].velFilter = (short)udInstVelFilter.Value;

            byte val = (byte)(99 + udInstVelFilter.Value);

            Program.module.SendNRPN(NRPN.InstLayerVelFilter, (byte)(val & 0x7F), (byte)((val & 0x80) > 0 ? 1 : 0));
        }

        private void udInstVelLevel_ValueChanged(object sender, EventArgs e)
        {
            Program.settings.kits[currentKit].instruments[currentInst].instLayers[CurrentLayer].velLevel = (short)udInstVelLevel.Value;

            Program.module.SendNRPN(NRPN.InstLayerVelLevel, (byte)udInstVelLevel.Value);
        }

        private void udInstVelPitch_ValueChanged(object sender, EventArgs e)
        {
            Program.settings.kits[currentKit].instruments[currentInst].instLayers[CurrentLayer].velPitch = (short)udInstVelPitch.Value;

            byte val = (byte)(99 + udInstVelPitch.Value);

            Program.module.SendNRPN(NRPN.InstLayerVelPitch, (byte)(val & 0x7F), (byte)((val & 0x80) > 0 ? 1 : 0));
        }

        private void frmMain_FormClosing(object sender, FormClosingEventArgs e)
        {
            Program.module.Close();
        }

        private void ddlInstruments_SelectedIndexChanged(object sender, EventArgs e)
        {
            Program.settings.kits[currentKit].instruments[currentInst].instLayers[CurrentLayer].category = (short)ddlCategories.SelectedIndex;
            Program.settings.kits[currentKit].instruments[currentInst].instLayers[CurrentLayer].sound = (short)ddlInstruments.SelectedIndex;

            short val = (short)(Program.settings.soundset.globalIDs[ddlCategories.SelectedIndex, ddlInstruments.SelectedIndex]);
            //MessageBox.Show("val: " + val + ", inst: " + Program.settings.soundset.instruments[ddlCategories.SelectedIndex][ddlInstruments.SelectedIndex]);
            Program.module.SendNRPN(NRPN.InstLayerPreset, (byte)(val & 0x7F), (byte)((val & 0xFF80) >> 7));
        }

        private void logToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Program.LogForm.Show();
        }

        private void newModuleFileToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (MessageBox.Show("Are you sure you want to create a new module file?\nNOTE: All unsaved changes will be lost!", "Create a new module file?", MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.Yes)
            {
                Program.settings.setDefaults();
                listInstruments.SelectedIndex = 0;
                updateInstrumentSettings(currentInst, 0);

                //MessageBox.Show("Module cleared!");

                setTitle("New Module");
            }

        }


#region Save
        private void menuSaveModule_Click(object sender, EventArgs e)
        {
            SaveFileDialog dlg = new SaveFileDialog();
            dlg.Filter = "DM10 Modules|*.dmm";
            dlg.DefaultExt = ".dmm";
            DialogResult res = dlg.ShowDialog();

            if (res == System.Windows.Forms.DialogResult.OK)
            {
                Program.settings.SaveModule(dlg.FileName);
            }

        }

        private void menuSaveKit_Click(object sender, EventArgs e)
        {
            SaveFileDialog dlg = new SaveFileDialog();
            dlg.Filter = "DM10 Kits|*.dmk";
            dlg.DefaultExt = ".dmk";
            DialogResult res = dlg.ShowDialog();

            if (res == System.Windows.Forms.DialogResult.OK)
            {
                Program.settings.SaveKit(dlg.FileName, currentKit);
            }
        }

        private void menuSaveInst_Click(object sender, EventArgs e)
        {
            SaveFileDialog dlg = new SaveFileDialog();
            dlg.Filter = "DM10 Instruments|*.dmi";
            dlg.DefaultExt = ".dmi";
            DialogResult res = dlg.ShowDialog();


            if (res == System.Windows.Forms.DialogResult.OK)
            {
                Program.settings.SaveInstrument(dlg.FileName, currentKit, currentInst);
            }

        }

#endregion


#region Load
        private void menuLoadModule_Click(object sender, EventArgs e)
        {
            OpenFileDialog dlg = new OpenFileDialog();
            dlg.Filter = "DM10 Modules|*.dmm";
            dlg.DefaultExt = ".dmm";
            DialogResult res = dlg.ShowDialog();

            if (res == System.Windows.Forms.DialogResult.OK)
            {
                Program.settings.LoadModule(dlg.FileName);
            }

            finishLoad();
        }

        public void finishLoad()
        {
            for (int i = 0; i < 100; ++i) stripKits.Items[i] = (i + 100) + " (" + Program.settings.kits[i].name + ")";
            stripKits.SelectedIndex = 0;
            listInstruments.SelectedIndex = 0; 
            updateInstrumentSettings(currentInst, 0);
        }

        private void menuLoadKit_Click(object sender, EventArgs e)
        {
            OpenFileDialog dlg = new OpenFileDialog();
            dlg.Filter = "DM10 Kits|*.dmk";
            dlg.DefaultExt = ".dmk";
            DialogResult res = dlg.ShowDialog();

            if (res == System.Windows.Forms.DialogResult.OK)
            {
                Program.settings.LoadKit(dlg.FileName, currentKit);
            }

            stripKits.Items[currentKit] = (currentKit + 100) + " (" + Program.settings.kits[currentKit].name + ")";

            listInstruments.SelectedIndex = 0;
            updateInstrumentSettings(currentInst, 0);



        }

        private void menuLoadInst_Click(object sender, EventArgs e)
        {
            OpenFileDialog dlg = new OpenFileDialog();
            dlg.Filter = "DM10 Instruments|*.dmi";
            dlg.DefaultExt = ".dmi";
            DialogResult res = dlg.ShowDialog();

            if (res == System.Windows.Forms.DialogResult.OK)
            {
                Program.settings.LoadInstrument(dlg.FileName, currentKit, currentInst);
                updateInstrumentSettings(listInstruments.SelectedIndex, 0);
            }
        }
#endregion

        
        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

#region FX

        private void ddlReverbType_SelectedIndexChanged(object sender, EventArgs e)
        {
            Program.settings.kits[currentKit].reverbType = (short)ddlReverbType.SelectedIndex;
            Program.module.SendNRPN(NRPN.ReverbPreset, ddlReverbType.SelectedIndex);
        }

        private void udReverbSize_ValueChanged(object sender, EventArgs e)
        {
            Program.settings.kits[currentKit].reverbSize = (short)udReverbSize.Value;

            Program.module.SendNRPN(NRPN.ReverbSize, (byte)udReverbSize.Value);
        }

        private void udReverbColor_ValueChanged(object sender, EventArgs e)
        {
            Program.settings.kits[currentKit].reverbColor = (short)udReverbColor.Value;
            Program.module.SendNRPN(NRPN.ReverbColor, (byte)udReverbColor.Value);
        }

        private void udReverbLevel_ValueChanged(object sender, EventArgs e)
        {
            Program.settings.kits[currentKit].reverbLevel = (short)udReverbLevel.Value;

            Program.module.SendNRPN(NRPN.ReverbLevel, (byte)udReverbLevel.Value);
        }

#endregion

        private void ddlFxType_SelectedIndexChanged(object sender, EventArgs e)
        {
            // Enable / disable fields based on selection
            int flags = DM10Kit.EnabledFXOptions[ddlFxType.SelectedIndex];

            lblFxLevel.Enabled = udFxLevel.Enabled = (flags & (int)DM10Kit.FXOptions.FXLevel) > 0 ? true : false;
            lblFxDepth.Enabled = udFxDepth.Enabled = (flags & (int)DM10Kit.FXOptions.FXDepth) > 0 ? true : false;
            lblFxRate.Enabled = udFxRate.Enabled = (flags & (int)DM10Kit.FXOptions.FXRate) > 0 ? true : false;
            lblFxDamp.Enabled = udFxDamp.Enabled = (flags & (int)DM10Kit.FXOptions.FXDamp) > 0 ? true : false;
            lblFxFeedbackL.Enabled = udFxFeedbackL.Enabled = (flags & (int)DM10Kit.FXOptions.FXFeedbackL) > 0 ? true : false;
            lblFxFeedbackR.Enabled = udFxFeedbackR.Enabled = (flags & (int)DM10Kit.FXOptions.FXFeedbackR) > 0 ? true : false;
            lblFxDelayL.Enabled = udFxDelayL.Enabled = (flags & (int)DM10Kit.FXOptions.FXDelayL) > 0 ? true : false;
            lblFxDelayR.Enabled = udFxDelayR.Enabled = (flags & (int)DM10Kit.FXOptions.FXDelayR) > 0 ? true : false;

            Program.settings.kits[currentKit].fxType = (short)ddlFxType.SelectedIndex;
            Program.module.SendNRPN(NRPN.DelayPreset, ddlFxType.SelectedIndex);
        }

        private void udFxLevel_ValueChanged(object sender, EventArgs e)
        {
            Program.settings.kits[currentKit].fxLevel = (short)udFxLevel.Value;

            Program.module.SendNRPN(NRPN.DelayLevel, (int)udFxLevel.Value);
        }

        private void udFxDamp_ValueChanged(object sender, EventArgs e)
        {
            Program.settings.kits[currentKit].fxDamp = (short)udFxDamp.Value;

            Program.module.SendNRPN(NRPN.DelayDamp, (int)udFxDamp.Value);
        }

        private void udFxDepth_ValueChanged(object sender, EventArgs e)
        {
            Program.settings.kits[currentKit].fxDepth = (short)udFxDepth.Value;

            Program.module.SendNRPN(NRPN.DelayDepth, (int)udFxDepth.Value);
        }

        private void udFxRate_ValueChanged(object sender, EventArgs e)
        {
            Program.settings.kits[currentKit].fxRate = (short)udFxRate.Value;

            Program.module.SendNRPN(NRPN.DelayRate, (int)udFxRate.Value);
        }

        private void udFxFeedbackL_ValueChanged(object sender, EventArgs e)
        {
            Program.settings.kits[currentKit].fxFeedbackL = (short)udFxFeedbackL.Value;

            Program.module.SendNRPN(NRPN.DelayFeedbackLeft, (int)udFxFeedbackL.Value);
        }

        private void udFxFeedbackR_ValueChanged(object sender, EventArgs e)
        {
            Program.settings.kits[currentKit].fxFeedbackR = (short)udFxFeedbackR.Value;

            Program.module.SendNRPN(NRPN.DelayFeedbackRight, (int)udFxFeedbackR.Value);
        }

        private void udFxDelayL_ValueChanged(object sender, EventArgs e)
        {
            Program.settings.kits[currentKit].fxDelayL = (short)udFxDelayL.Value;

            Program.module.SendNRPN(NRPN.DelayTimeLeft, (int)udFxDelayL.Value);
        }

        private void udFxDelayR_ValueChanged(object sender, EventArgs e)
        {
            Program.settings.kits[currentKit].fxDelayR = (short)udFxDelayR.Value;

            Program.module.SendNRPN(NRPN.DelayTimeRight, (int)udFxDelayR.Value);
        }

        private void udEqLfGain_ValueChanged(object sender, EventArgs e)
        {
            Program.settings.kits[currentKit].eqLFGain = (short)udEqLfGain.Value;

            Program.module.SendNRPN(NRPN.LowEQGain, (int)(udEqLfGain.Value + 60));
        }

        private void ddlEqLfFreq_SelectedIndexChanged(object sender, EventArgs e)
        {
            Program.settings.kits[currentKit].eqLFFreq = (short)ddlEqLfFreq.SelectedIndex;

            Program.module.SendNRPN(NRPN.LowEQFreq, (int)ddlEqLfFreq.SelectedIndex);
        }

        private void udEqHfGain_ValueChanged(object sender, EventArgs e)
        {
            Program.settings.kits[currentKit].eqHFGain = (short)udEqHfGain.Value;

            Program.module.SendNRPN(NRPN.HighEQGain, (int)(udEqHfGain.Value + 60));
        }

        private void ddlEqHfFreq_SelectedIndexChanged(object sender, EventArgs e)
        {
            Program.settings.kits[currentKit].eqHFFreq = (short)ddlEqHfFreq.SelectedIndex;

            Program.module.SendNRPN(NRPN.HighEQFreq, (int)ddlEqHfFreq.SelectedIndex);
        }

        private void ddlCompType_SelectedIndexChanged(object sender, EventArgs e)
        {
            Program.settings.kits[currentKit].compType = (short)ddlCompType.SelectedIndex;

            Program.module.SendNRPN(NRPN.CompressorPreset, (int)ddlCompType.SelectedIndex);
        }

        private void udCompLevel_ValueChanged(object sender, EventArgs e)
        {
            Program.settings.kits[currentKit].compLevel = (short)udCompLevel.Value;

            Program.module.SendNRPN(NRPN.CompressRatio, (int)udCompLevel.Value);
        }

        private void udCompOutLevel_ValueChanged(object sender, EventArgs e)
        {
            Program.settings.kits[currentKit].compOutLevel = (short)udCompOutLevel.Value;

            Program.module.SendNRPN(NRPN.CompressLevel, (int)(udCompOutLevel.Value + 24));
        }

        private void trkPan_Scroll(object sender, EventArgs e)
        {
            updatePanLabel();

            Program.settings.kits[currentKit].instruments[currentInst].instLayers[CurrentLayer].pan = (short)(trkInstPan.Value);

            Program.module.SendNRPN(NRPN.InstLayerPan, (byte)(trkInstPan.Value + 14));
        }

        private void updatePanLabel()
        {
            if (trkInstPan.Value == 50) lblPanValue.Text = "MID";
            else if (trkInstPan.Value < 50) lblPanValue.Text = "L" + (50 - trkInstPan.Value).ToString();
            else lblPanValue.Text = "R" + (trkInstPan.Value - 50).ToString();
        }

        private void rdoOutputMain_CheckedChanged(object sender, EventArgs e)
        {
            if (rdoOutputMain.Checked)
            {
                Program.settings.kits[currentKit].instruments[currentInst].instLayers[CurrentLayer].output = 0;

                Program.module.SendNRPN(NRPN.InstOutput, 0);
            }
        }

        private void rdoOutputAux_CheckedChanged(object sender, EventArgs e)
        {
            if (rdoOutputAux.Checked)
            {
                Program.settings.kits[currentKit].instruments[currentInst].instLayers[CurrentLayer].output = 1;

                Program.module.SendNRPN(NRPN.InstOutput, 1);
            }
        }

        private void rdoPriorityLow_CheckedChanged(object sender, EventArgs e)
        {
            if (rdoPriorityLow.Checked)
            {
                Program.settings.kits[currentKit].instruments[currentInst].instLayers[CurrentLayer].priority = 0;

                Program.module.SendNRPN(NRPN.InstPriority, 0);
            }
        }

        private void rdoPriorityMed_CheckedChanged(object sender, EventArgs e)
        {
            if (rdoPriorityMed.Checked)
            {
                Program.settings.kits[currentKit].instruments[currentInst].instLayers[CurrentLayer].priority = 1;

                Program.module.SendNRPN(NRPN.InstPriority, 1);
            }
        }

        private void rdoPriorityHigh_CheckedChanged(object sender, EventArgs e)
        {
            if (rdoPriorityHigh.Checked)
            {
                Program.settings.kits[currentKit].instruments[currentInst].instLayers[CurrentLayer].priority = 2;

                Program.module.SendNRPN(NRPN.InstPriority, 2);
            }
        }

        private void rdoPlaybackPoly_CheckedChanged(object sender, EventArgs e)
        {
            if (rdoPlaybackPoly.Checked)
            {
                Program.settings.kits[currentKit].instruments[currentInst].instLayers[CurrentLayer].monoPlayback = 0;

                Program.module.SendNRPN(NRPN.InstIsMono, 0);
            }
        }

        private void rdoPlaybackMono_CheckedChanged(object sender, EventArgs e)
        {
            if (rdoPlaybackMono.Checked) 
            {
                Program.settings.kits[currentKit].instruments[currentInst].instLayers[CurrentLayer].monoPlayback = 1;

                Program.module.SendNRPN(NRPN.InstIsMono, 1);
            }
        }

        private void rdoFilterTypeLowpass_CheckedChanged(object sender, EventArgs e)
        {
            if (rdoFilterTypeLowpass.Checked)
            {
                Program.settings.kits[currentKit].instruments[currentInst].instLayers[CurrentLayer].filtertype = 0;

                Program.module.SendNRPN(NRPN.InstLayerFilterType, 0);
            }
        }

        private void rdoFilterTypeHighpass_CheckedChanged(object sender, EventArgs e)
        {
            if (rdoFilterTypeHighpass.Checked)
            {
                Program.settings.kits[currentKit].instruments[currentInst].instLayers[CurrentLayer].filtertype = 1;

                Program.module.SendNRPN(NRPN.InstLayerFilterType, 1);
            }
        }

        private void renameKitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Program.RenameForm.Setup(currentKit + 100, Program.settings.kits[currentKit].name);
            Program.RenameForm.StartPosition = FormStartPosition.CenterParent;
            Program.RenameForm.ShowDialog();
        }


        public void RenameCurrentKit(string newName)
        {
            Program.settings.kits[currentKit].name = newName;
            stripKits.Items[currentKit] = (currentKit + 100) + " (" + newName + ")";
        }

        private void rdoLayerA_CheckedChanged(object sender, EventArgs e)
        {
            updateInstrumentSettings(currentInst, CurrentLayer);
        }

        private void rdoLayerB_CheckedChanged(object sender, EventArgs e)
        {
            updateInstrumentSettings(currentInst, CurrentLayer);
        }

        private void udMIDIChannel_ValueChanged(object sender, EventArgs e)
        {
            Program.settings.kits[currentKit].instruments[currentInst].midi.channel = (short)udMIDIChannel.Value;

            Program.module.SendNRPN(NRPN.InstMidiChannel, (short)udMIDIChannel.Value - 1);
        }

        private void udMIDINote_ValueChanged(object sender, EventArgs e)
        {
            Program.settings.kits[currentKit].instruments[currentInst].midi.note = (short)udMIDINote.Value;
            lblMIDINote.Text = GetNoteName((int)udMIDINote.Value);

            Program.module.SendNRPN(NRPN.InstMidiNote, (short)udMIDINote.Value);
        }

        private void ddlMIDIGateTime_SelectedIndexChanged(object sender, EventArgs e)
        {
            Program.settings.kits[currentKit].instruments[currentInst].midi.gateTime = (short)ddlMIDIGateTime.SelectedIndex;

            Program.module.SendNRPN(NRPN.InstGateTime, (short)ddlMIDIGateTime.SelectedIndex + 1);
        }


        private void udMIDIChordNote2_ValueChanged(object sender, EventArgs e)
        {
            Program.settings.kits[currentKit].instruments[currentInst].midi.note2 = (short)udMIDIChordNote2.Value;
            lblMIDINote2.Text = GetNoteName((int)udMIDIChordNote2.Value);

            Program.module.SendNRPN(NRPN.InstXtraNotes0, (short)udMIDIChordNote2.Value + 1);
        }

        private void udMIDIChordNote3_ValueChanged(object sender, EventArgs e)
        {
            Program.settings.kits[currentKit].instruments[currentInst].midi.note3 = (short)udMIDIChordNote3.Value;
            lblMIDINote3.Text = GetNoteName((int)udMIDIChordNote3.Value);

            Program.module.SendNRPN(NRPN.InstXtraNotes1, (short)udMIDIChordNote3.Value + 1);
        }

        private void udMIDIChordNote4_ValueChanged(object sender, EventArgs e)
        {
            Program.settings.kits[currentKit].instruments[currentInst].midi.note4 = (short)udMIDIChordNote4.Value;
            lblMIDINote4.Text = GetNoteName((int)udMIDIChordNote4.Value);

            Program.module.SendNRPN(NRPN.InstXtraNotes2, (short)udMIDIChordNote4.Value + 1);
        }

        private void rdoMIDINoteNotSent_CheckedChanged(object sender, EventArgs e)
        {
            if (rdoMIDINoteNotSent.Checked)
            {
                Program.settings.kits[currentKit].instruments[currentInst].midi.sendNoteOff = 0;

                Program.module.SendNRPN(NRPN.InstOffMode, 0);
            }
        }

        private void rdoMIDINoteSent_CheckedChanged(object sender, EventArgs e)
        {
            if (rdoMIDINoteSent.Checked)
            {
                Program.settings.kits[currentKit].instruments[currentInst].midi.sendNoteOff = 1;

                Program.module.SendNRPN(NRPN.InstOffMode, 1);
            }
        }

        private void rdoMIDINoteAlternate_CheckedChanged(object sender, EventArgs e)
        {
            if (rdoMIDINoteAlternate.Checked)
            {
                Program.settings.kits[currentKit].instruments[currentInst].midi.sendNoteOff = 2;

                Program.module.SendNRPN(NRPN.InstOffMode, 2);
            }
        }

        private void rdoMIDIChordOff_CheckedChanged(object sender, EventArgs e)
        {
            if (rdoMIDIChordOff.Checked)
            {
                Program.settings.kits[currentKit].instruments[currentInst].midi.chordMode = 0;

                udMIDIChordNote2.Enabled = false;
                udMIDIChordNote3.Enabled = false;
                udMIDIChordNote4.Enabled = false;

                Program.module.SendNRPN(NRPN.InstChordMode, 0);
            }
        }

        private void rdoMIDIChord_CheckedChanged(object sender, EventArgs e)
        {
            if (rdoMIDIChord.Checked)
            {
                Program.settings.kits[currentKit].instruments[currentInst].midi.chordMode = 1;

                udMIDIChordNote2.Enabled = true;
                udMIDIChordNote3.Enabled = true;
                udMIDIChordNote4.Enabled = true;
            

                Program.module.SendNRPN(NRPN.InstChordMode, 1);
            }
        }

        private void rdoMIDIChordArpeggio_CheckedChanged(object sender, EventArgs e)
        {
            if (rdoMIDIChordArpeggio.Checked)
            {
                Program.settings.kits[currentKit].instruments[currentInst].midi.chordMode = 2;

                udMIDIChordNote2.Enabled = true;
                udMIDIChordNote3.Enabled = true;
                udMIDIChordNote4.Enabled = true;

                Program.module.SendNRPN(NRPN.InstChordMode, 2);
            }
        }



        private string GetNoteName(int note)
        {
            if (note < 0) return "Off";
            string[] notes = new string[] { "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" };

            int octave = (note / 12) - 2; // Ranges from -2 to 8

            return notes[note % 12] + octave;
        }

        private void aboutDMEditorToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (Program.AboutForm.IsDisposed) Program.AboutForm = new frmAbout();
            Program.AboutForm.StartPosition = FormStartPosition.CenterParent;
            Program.AboutForm.ShowDialog();
        }

        private void numericUpDown1_ValueChanged(object sender, EventArgs e)
        {
            Program.module.SendNRPN(NRPN.InstLayerPreset, (byte)((int)numericUpDown1.Value & 0x7F), (byte)(((int)numericUpDown1.Value & 0xFF80) >> 7));
        }

        private void frmMain_FormClosed(object sender, FormClosedEventArgs e)
        {
            Program.StartupForm.Dispose();
        }

        public void setTitle(string fileName)
        {
            Program.MainForm.Text = "DMEditor - " + fileName + " (" + Program.settings.soundsetName + ")";
        }

        private void resetKitToDefaultsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            int kit = stripKits.SelectedIndex;

            if (MessageBox.Show("Are you sure you want to reset kit #" + (kit + 100) + " to defaults?\n\nAll unsaved changes will be lost!", "Create a new module file?", MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.Yes)
            {
                Program.settings.kits[kit].setDefaults(Program.settings.currentSoundset);

                listInstruments.SelectedIndex = 0;
                updateInstrumentSettings(currentInst, 0);

                Program.module.UploadKit(kit);
            }


        }

        private void copyKitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (Program.CopyForm.IsDisposed) Program.CopyForm = new frmCopy();

            Program.CopyForm.SetupForm();
            Program.CopyForm.ShowDialog();
        }
        /*
        private void defaultInstrumentToolStripMenuItem_Click(object sender, EventArgs e)
        {
            int kit = stripKits.SelectedIndex;
            if (MessageBox.Show("Are you sure you want to reset " + listInstruments.Items[listInstruments.SelectedIndex] + " in kit #" + (kit + 100) + " to defaults?\n\nAll unsaved changes will be lost!", "Create a new module file?", MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.Yes)
            {
                Program.settings.kits[kit].instruments[listInstruments.SelectedIndex]. setDefaults(Program.settings.currentSoundset);

                listInstruments.SelectedIndex = 0;
                updateInstrumentSettings(currentInst, 0);

                Program.module.UploadKit(kit);
            }

        }*/

    }
}
